/*
 * Copyright (c) 2008-2014, RF-Embedded GmbH
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 *  1. Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, 
 *     this list of conditions and the following disclaimer in the 
 *     documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.rfe.helper;

import java.util.List;

/**
 * The class Hleper contains some functions that are used by the protocol handler for operations 
 * with arrays and lists and for converting data into a string.
 */
public class JrfeHelper {
	
	/**
	 * Converts a list of bytes to a byte array
	 * @param in	List of bytes
	 * @return		The new byte array
	 */
	public static byte[] toByteArray(List<Byte> in) {
	    final int n = in.size();
	    byte ret[] = new byte[n];
	    for (int i = 0; i < n; i++) {
	        ret[i] = in.get(i);
	    }
	    return ret;
	}
	
	/**
	 * Adds a given byte array to the end of a given byte list
	 * @param src		The byte array
	 * @param dest		The list of bytes, where the byte array should be added
	 */
	public static void addRange(byte[] src, List<Byte> dest)
	{
	    final int n = src.length;
	    for (int i = 0; i < n; i++) {
	    	dest.add(src[i]);
	    }		
	}
	
	
	
	/**
	 * Parses a byte from the given position from the given array
	 * @param data		The byte array 
	 * @param pos		The position of the byte
	 * @return			The parsed byte
	 */
	public static Byte toByte(byte[] data, int pos)
	{
		Byte value = (Byte)data[pos];
		return value;
	}
	
	/**
	 * Parses a short from the given position from the given array
	 * @param data		The byte array 
	 * @param pos		The position of the short
	 * @return			The parsed short
	 */
	public static Short toShort(byte[] data, int pos, int size)
	{
		short value = 0;
		for(int i = 0; i < size; i++)
		{
			value <<= 8;
			value |= (0xFF & data[i+pos]);
		}
		return (Short)value;
	}
	
	/**
	 * Parses an integer from the given position from the given array
	 * @param data		The byte array 
	 * @param pos		The position of the integer
	 * @return			The parsed integer
	 */
	public static Integer toInteger(byte[] data, int pos, int size)
	{
		int value = 0;
		for(int i = 0; i < size; i++)
		{
			value <<= 8;
			value |= (0xFF & data[i+pos]);
		}
		return (Integer)value;
	}
	
	/**
	 * Parses a long from the given position from the given array
	 * @param data		The byte array 
	 * @param pos		The position of the long
	 * @return			The parsed long
	 */
	public static Long toLong(byte[] data, int pos, int size)
	{
		long value = 0L;
		for(int i = 0; i < size; i++)
		{
			value <<= 8;
			value |= (0xFF & data[i+pos]);
		}
		return (Long)value;
	}
	
	
	
	/**
	 * Converts a list of bytes to a hex string.
	 * @param array		The list of bytes
	 * @return			The list of bytes in a hex string
	 */
	public static String toHexString(List<Byte> array)
	{
		return convertToHexString(toByteArray(array));
	}
	
	/**
	 * Converst a byte array to a hex string
	 * @param array		The byte array
	 * @return			The byte array in a hex string
	 */
	public static String toHexString(byte[] array)
	{
		return convertToHexString(array);
	}
	
	/**
	 * Variable used for converting a byte into a hex string
	 */
	final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
	
	/**
	 * Private function to convert a byte array to a hex string.
	 * @param data		The byte array
	 * @return			The hex string
	 */
	private static String convertToHexString (byte[] data)
	{
		if(data.length == 0)
			return "<null>";
		
		char[] hexChars = new char[(data.length * 3) - 1];
	    int v;
	    for ( int j = 0; j < data.length; j++ ) {
	        v = data[j] & 0xFF;
	        hexChars[j * 3] = hexArray[v >>> 4];
	        hexChars[j * 3 + 1] = hexArray[v & 0x0F];
	        if(j < (data.length-1))
		        hexChars[j * 3 + 2] = '-';
	    }
	    return new String(hexChars);
	}

	/**
	 * Converts a byte into a hex string of size 2
	 * @param value		The byte value
	 * @return			The hex string
	 */
	public static String toHexString(Byte value)
	{
		return toHexString(value, 2);
	}
	
	/**
	 * Converts a byte into a hex string
	 * @param value		The byte value
	 * @param length	The desired length of the string
	 * @return			The hex string
	 */
	public static String toHexString(Byte value, int length)
	{
		StringBuilder str = new StringBuilder();
		String s = Integer.toHexString(0xFF & value);
		int sizeToFill = length - s.length();
		for(int i = 0; i < sizeToFill; i++)
			str.append("0");
		str.append(s);
		if(sizeToFill < 0)
			for(int i = 0; i < (sizeToFill*-1); i++)
				str.deleteCharAt(0);
		return str.toString().toUpperCase();
	}
	
	/**
	 * Converts a short into a hex string of size 4
	 * @param value		The short value
	 * @return			The hex string
	 */
	public static String toHexString(Short value)
	{
		return toHexString(value, 4);
	}
	
	/**
	 * Converts a short into a hex string
	 * @param value		The short value
	 * @param length	The desired length of the string
	 * @return			The hex string
	 */
	public static String toHexString(Short value, int length)
	{
		StringBuilder str = new StringBuilder();
		String s = Integer.toHexString(0xFFFF & value);
		int sizeToFill = length - s.length();
		for(int i = 0; i < sizeToFill; i++)
			str.append("0");
		str.append(s);
		if(sizeToFill < 0)
			for(int i = 0; i < (sizeToFill*-1); i++)
				str.deleteCharAt(0);
		return str.toString().toUpperCase();
	}
	
	/**
	 * Converts an integer into a hex string of size 8
	 * @param value		The integer value
	 * @return			The hex string
	 */
	public static String toHexString(Integer value)
	{
		return toHexString(value, 8);
	}
	
	/**
	 * Converts an integer into a hex string
	 * @param value		The integer value
	 * @param length	The desired length of the string
	 * @return			The hex string
	 */
	public static String toHexString(Integer value, int length)
	{
		StringBuilder str = new StringBuilder();
		String s = Integer.toHexString(0xFFFFFFFF & value);
		int sizeToFill = length - s.length();
		for(int i = 0; i < sizeToFill; i++)
			str.append("0");
		str.append(s);
		if(sizeToFill < 0)
			for(int i = 0; i < (sizeToFill*-1); i++)
				str.deleteCharAt(0);
		return str.toString().toUpperCase();
	}

	/**
	 * Converts a long into a hex string of size 8
	 * @param value		The long value
	 * @return			The hex string
	 */
	public static String toHexString(Long value)
	{
		return toHexString(value, 16);
	}

	/**
	 * Converts a long into a hex string
	 * @param value		The long value
	 * @param length	The desired length of the string
	 * @return			The hex string
	 */
	public static String toHexString(Long value, int length)
	{
		StringBuilder str = new StringBuilder();
		String s = Long.toHexString(0xFFFFFFFFFFFFFFFFL & value);
		int sizeToFill = length - s.length();
		for(int i = 0; i < sizeToFill; i++)
			str.append("0");
		str.append(s);
		if(sizeToFill < 0)
			for(int i = 0; i < (sizeToFill*-1); i++)
				str.deleteCharAt(0);
		return str.toString().toUpperCase();
	}
	

}
